package com.companyname.demo.cod.service;

import com.companyname.demo.cod.dao.UserInfoMapper;
import com.companyname.demo.cod.domain.AjaxResult;
import com.companyname.demo.cod.domain.UserInfo;
import com.companyname.demo.cod.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import tk.mybatis.mapper.util.Assert;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Description:
 * @Author: xglsr
 * @Date: 2021/6/4 12:43
 */
@Service
@Slf4j
public class LoginService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    public AjaxResult doRegistry(String userName, String password) {
        //1.非空校验
        Assert.notEmpty(userName, "用户名不得为空");
        Assert.notEmpty(password, "密码不得为空");

        //2.userName唯一性校验
        UserInfo queryVO = new UserInfo();
        queryVO.setUserName(userName);
        UserInfo userInfoDB = userInfoMapper.selectOne(queryVO);
        if (userInfoDB != null) {
            return AjaxResult.error("用户名已存在！");
        }
        //3.对密码使用RSA算法解密、使用salt+md5算法加密
        String decryptedPwd = RSAUtil.decryptStringByJs(password);
        log.info("解密后的password={}", decryptedPwd);
        String salt = UuidUtil.getUUID();
        password = MD5Util.encodeBySalt(decryptedPwd, salt);
        //4.保存入库
        queryVO.setPassword(password);
        queryVO.setSalt(salt);
        queryVO.setId(UuidUtil.getUUID());
        userInfoMapper.insert(queryVO);
        return AjaxResult.success("注册成功！");
    }

    public AjaxResult doLogin(String userName, String password, HttpServletResponse response) {
        //1.非空校验
        Assert.notEmpty(userName, "用户名不得为空");
        Assert.notEmpty(password, "密码不得为空");
        //2.userName是否存在
        UserInfo queryVO = new UserInfo();
        queryVO.setUserName(userName);
        UserInfo userInfoDB = userInfoMapper.selectOne(queryVO);
        if (ObjectUtils.isEmpty(userInfoDB)) {
            return AjaxResult.error401("用户或密码错误！");
        }
        //3.对密码使用RSA算法解密、使用salt+md5算法加密,验证密码
        String salt = userInfoDB.getSalt();
        String decryptedPwd = RSAUtil.decryptStringByJs(password);
        password = MD5Util.encodeBySalt(decryptedPwd, salt);
        if (!userInfoDB.getPassword().equals(password)) {
            return AjaxResult.error401("用户或密码错误！");
        }
        //4.生成JWT，TODO:以下payload根据业务需求自定义
        Map<String, Object> jwtPayloadUserInfo = new HashMap<>();
        jwtPayloadUserInfo.put("userName", userName);
        jwtPayloadUserInfo.put("userType", "Admin");
        jwtPayloadUserInfo.put("loginTime", MultiThreadDateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        long nowMilliSeconds = new Date().getTime();
        jwtPayloadUserInfo.put("timestamp", nowMilliSeconds);//该字段用来验证jwt的有效性，和redis的jwtsalt[1]比较
        String jwt = JwtUtil.createJwt(jwtPayloadUserInfo, salt);

        //5.保存(覆盖)用户信息、salt_timestamp到redis中
        redisTemplate.opsForValue().set("jwtsalt:" + userName, salt + "." + nowMilliSeconds);
        redisTemplate.opsForValue().getOperations().expire("jwtsalt:" + userName, 24, TimeUnit.HOURS);
        redisTemplate.opsForHash().put("userInfo", userName, userInfoDB);

        //6.response.cookie加入JWT，重定向到首页
        Cookie cookie = new Cookie("user_token", jwt);
        cookie.setPath("/");//这里需要设置，否则跳转页面时浏览器不能写入cookie到域名下
        response.addCookie(cookie);
        log.info("用户{}登录成功！", userName);
        return AjaxResult.success("login success！");
    }
}
